package com.zshan.clinic.common.util.token;

import com.nimbusds.jose.JWSAlgorithm;
import com.nimbusds.jose.JWSHeader;
import com.nimbusds.jose.JWSVerifier;
import com.nimbusds.jose.crypto.MACSigner;
import com.nimbusds.jose.crypto.MACVerifier;
import com.nimbusds.jwt.JWTClaimsSet;
import com.nimbusds.jwt.SignedJWT;
import com.zshan.clinic.common.constant.CommonConstant;
import com.zshan.clinic.common.exception.BusinessFailException;
import com.zshan.clinic.common.util.date.DateTimeUtils;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;
import java.util.Objects;

/**
 * token工具类
 */
@Slf4j
public class JWTHS256 {

    /**
     * 创建秘钥
     */
    private static final byte[] SECRET = "Z9MNSobBRCHGIO0OfZS6MNISoYbBRUCHGAIO0NfSZMNSobBRCHGIO0OfZS6MNISoYbBRUCHGAIO0NfSZMNSobBRCHGIO0OfZS6MNISoYbBRUCHGAIO0NfSZMNSobBRCHGIO0OfZ".getBytes();


    /**
     * 生成Token
     *
     * @param userId
     * @return
     */
    public static String buildJWT(String userId) {
        try {
            /**
             * 1.创建一个32-byte的密匙
             */
            MACSigner macSigner = new MACSigner(SECRET);
            /**
             * 2. 建立payload 载体
             */
            JWTClaimsSet claimsSet = new JWTClaimsSet.Builder()
                    .claim("userId", userId)
                    .expirationTime(DateTimeUtils.plusSeconds(new Date(), CommonConstant.DEFAULT_2))
                    .build();

            /**
             * 3. 建立签名
             */
            SignedJWT signedJWT = new SignedJWT(new JWSHeader(JWSAlgorithm.HS256), claimsSet);
            signedJWT.sign(macSigner);

            /**
             * 4. 生成token
             */
            String token = signedJWT.serialize();
            return token;
        } catch (Exception e) {
            log.error("token生成失败",e);
            throw new BusinessFailException("网络繁忙，请稍后再试");
        }
    }


    /**
     * 校验token
     *
     * @param token
     * @return
     */
    public static String validateToken(String token) {
        try {
            SignedJWT jwt = SignedJWT.parse(token);
            JWSVerifier verifier = new MACVerifier(SECRET);
            //校验是否有效
            if (!jwt.verify(verifier)) {
                throw new BusinessFailException("无效的Token");
            }
            //校验超时
            Date expirationTime = jwt.getJWTClaimsSet().getExpirationTime();
            if (expirationTime != null) {
                if(DateTimeUtils.secondsBetween(new Date(),expirationTime) < 0){
                    throw new BusinessFailException("Token已过期");
                }
            }
            //获取载体中的数据
            Object userId = jwt.getJWTClaimsSet().getClaim("userId");
            //是否有openUid
            if (Objects.isNull(userId)) {
                throw new BusinessFailException("账号为空");
            }
            return userId.toString();
        } catch (BusinessFailException e) {
            log.error("token解析失败",e);
            throw e;
        } catch (Exception e) {
            log.error("token解析失败",e);
            throw new BusinessFailException("网络繁忙，请稍后再试");
        }
    }


    public static void main(String[] args) throws InterruptedException {
        String token = JWTHS256.buildJWT("1");
        System.out.println(token);
        //解密token
        String account = JWTHS256.validateToken(token);
        System.out.println("校验token成功，token的账号：" + account);

        //测试过期
        Thread.sleep(3 * 1000);
        account = JWTHS256.validateToken(token);
        System.out.println("校验token成功，token的账号：" + account);
    }

}
